package com.beiding.my.mql.utils;

import java.util.*;


public class SubMqlHide {

    //前置符号
    private String preSymbol = "(";

    //后置符号
    private String postSymbol = ")";

    //原始文本
    private String original;

    //使用隐藏区块
    private List<Block> hindBlocks = new ArrayList<>();

    //隐藏之后的结果
    private String result;

    private char hideChar = ' ';

    public String getPreSymbol() {
        return preSymbol;
    }

    public void setPreSymbol(String preSymbol) {
        this.preSymbol = preSymbol;
    }

    public String getPostSymbol() {
        return postSymbol;
    }

    public void setPostSymbol(String postSymbol) {
        this.postSymbol = postSymbol;
    }

    public void setHideChar(char hideChar) {
        this.hideChar = hideChar;
    }

    public char getHideChar() {
        return hideChar;
    }

    public SubMqlHide(String original) {
        this.original = original;
    }

    //执行隐藏操作
    public void hide() {


        StringHide stringHide = MqlUtils.hideString(original);

        //首先屏蔽掉字符串
        String noString = stringHide.getResult();

        List<Symbol> symbols = new ArrayList<>();

        int index = 0;

        while (true) {
            index = noString.indexOf(preSymbol, index);
            if (index == -1) {
                break;
            } else {
                Symbol symbol = new Symbol();
                symbol.type = 0;
                symbol.setIndex(index);
                symbols.add(symbol);
                index += preSymbol.length();
            }
        }

        index = 0;

        while (true) {
            index = noString.indexOf(postSymbol, index);
            if (index == -1) {
                break;
            } else {
                Symbol symbol = new Symbol();
                symbol.type = 1;
                symbol.setIndex(index);
                symbols.add(symbol);
                index += postSymbol.length();
            }
        }

        symbols.sort(Comparator.comparingInt(Position::getIndex));

        //区块
        Stack<Block> blocks = new Stack<>();

        //屏蔽掉的子句和结果都是带有字符串的
        char[] chars = original.toCharArray();

        for (Symbol symbol : symbols) {
            if (symbol.type == 0) {
                Block block = new Block();
                block.setStart(symbol.getIndex() + preSymbol.length());
                blocks.push(block);
            } else {


                Block pop = blocks.pop();

                //区块中
                pop.setEnd(symbol.getIndex() - postSymbol.length());

                pop.cutText(original);

                //只隐藏最外层的子句
                if (blocks.size() == 0 && MqlUtils.isMql(pop.getText())) {

                    hindBlocks.add(pop);

                    //将对应位置的文本隐藏处理
                    for (int i = pop.start; i <= pop.end; i++) {
                        chars[i] = hideChar;
                    }
                }
            }
        }


        //result中总是已经隐藏后的结果
        result = new String(chars);

        if (blocks.size() != 0) {
            throw new RuntimeException(preSymbol + "" + postSymbol + "  前后符号不匹配:" + original);
        }

    }

    private static class Symbol extends Position {
        //类型
        int type;
    }

    public String getResult() {
        return result;
    }

    public List<Block> getHindBlocks() {
        return hindBlocks;
    }

    public static void main(String[] args) {

        StringHide hide = new StringHide("select from xxx in (select xxxx) 'abc' xx in (select kkkk)  'aaa'", "'");

        hide.hide();

        List<Block> hindBlocks = new ArrayList<>(hide.getBlocks());

        SubMqlHide subMqlHide = new SubMqlHide(hide.getResult());

        subMqlHide.hide();

        hindBlocks.addAll(subMqlHide.getHindBlocks());

        Map<Pair, String> map = new HashMap<>();

        for (Block hindBlock : hindBlocks) {
            map.put(hindBlock, "这是一段测试的文本");
        }

        System.out.println(MqlUtils.recover(subMqlHide.getResult(), map));

    }


}
